//
// Created by tunm on 2024/3/14.
//

#include "predictor.h"
#include "serror.h"
#include "log.h"
#include "text_process/text_processing.h"

namespace solex {


int32_t Predictor::Initialization(const Configuration &param) {
    auto initTask = [this, param]() -> int32_t {
        this->m_semantic_cls_ = std::make_shared<SemanticCls>();
        int32_t result = this->m_semantic_cls_->Initialization(param.folderPath);
        m_initialized_ = (result == SSUCCEED); // Let SSUCCEED be a sign of success
        m_init_error_code_ = result;
        if (m_initialized_) {
            LOGD("Initialization successful.");
        } else {
            LOGE("Initialization failure: %d", result);
        }
        return result;
    };
    // Start asynchronous tasks
    m_init_future_ = std::async(std::launch::async, initTask);
    LOGD("Start initialization...");
    m_threshold_ = param.threshold;

    // You can return immediately, and the asynchronous task runs in the background
    return SSUCCEED;
}

void Predictor::_waiting() {
    // If the future is valid and has an asynchronous task, we wait for it to complete
    if (m_init_future_.valid()) {
        m_init_future_.wait(); // Blocks until the initialization task completes
    }
}

int32_t Predictor::AnalyseSentence(const std::string &sentence, AnalysisResult &output) {
    std::lock_guard<std::mutex> guard(m_mutex);
    _waiting(); // Make sure initialization is complete

    if (!m_initialized_) {
        return m_init_error_code_;
    }

    SemanticCls::SemanticPredictResult clsResult;
    auto ret = m_semantic_cls_->Predict(sentence, clsResult);
    if (ret != SSUCCEED) {
        return ret;
    }
    output.clsIndex = -1;
    if (clsResult.probability > m_threshold_) {
        // Specialized commands that carry parameters
        if (clsResult.idx == 0 || clsResult.idx == 1)  {
            auto args = ExtractAndSortNumbers(clsResult.cutWords, true);
            if (!args.empty()) {
                output.label = clsResult.label;
                output.probability = clsResult.probability;
                output.clsIndex = clsResult.idx;
                output.specialInt = args;
            }
        } else {
            // normal cases
            output.label = clsResult.label;
            output.probability = clsResult.probability;
            output.clsIndex = clsResult.idx;
        }
    }

    return SSUCCEED;
}

Predictor::Predictor() = default;


}   // namespace solex